/*
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
#include <comic_scrolling.h>
#include <comic.h>
#include <Ecore.h>
#include <string.h>
#include <debug.h>


extern struct comic_reader_guis *comic;
struct mouse_status {
	int pressed;
	int s_x, s_y;
	int x, y;
};

static struct  mouse_status  * mouse = NULL;
static struct  mouse_status  * zoom_status = NULL;

// returns 0 means no change
// 1 means next page
// -1 means last page
static int _check_if_change_page(struct comic_reader_guis *comic, struct mouse_status *mouse) {
	int xdiff;
	const double PAGE_THRUSHHOLD = 0.30;
	struct comic_page *left;
	struct comic_page *right;
	if (!comic) return 0;
	if (!comic->book) return 0;
	if (!mouse) return 0;
	xdiff = mouse->x - mouse->s_x;
	left = the_page_at_left();
	right = the_page_at_right();
	if (xdiff > 0 && left == NULL) {
		xdiff = 0;
	} else if (xdiff < 0  && right == NULL) {
		xdiff = 0;
	}
	if (xdiff > 0 &&
	        (double) (left->page_x + left->page_w + xdiff) > (double)(WIDTH()*PAGE_THRUSHHOLD) ) {  // turn to the page of left
		debug("left page %d+%d+%d=%d\n", left->page_x , left->page_w, xdiff, left->page_x + left->page_w + xdiff);
		if (comic->config->reading_seq == RIGHT_TO_LEFT) {
			return 1;
		}
		return -1;
	}
	if (xdiff < 0 &&
	        (double) (right->page_x + xdiff) < (double) (WIDTH()* (1 - PAGE_THRUSHHOLD))) {
		if (comic->config->reading_seq == RIGHT_TO_LEFT) {
			return -1;
		}
		return 1;
	}
	return 0;
}

static void _calculate_x_y_diff (struct comic_reader_guis *comic,
                                 struct mouse_status *mouse,
                                 int *xdiff,
                                 int *ydiff) {
	if (!comic) return;
	if (!comic->book) return;
	if (!mouse) return;
	*xdiff = mouse->x - mouse->s_x;
	*ydiff = mouse->y - mouse->s_y;
	if (*xdiff > 0  &&
	        comic->book->current_page->page_x + *xdiff > 0 &&
	        the_page_at_left() == NULL) {
		*xdiff = -comic->book->current_page->page_x;
	} else if (*xdiff < 0 &&
	           comic->book->current_page->page_x + comic->book->current_page->page_w + *xdiff < WIDTH() &&
	           the_page_at_right() == NULL) {
		*xdiff =  WIDTH() - (comic->book->current_page->page_x + comic->book->current_page->page_w);
	}
	if (*ydiff > 0  &&
	        comic->book->current_page->page_y + *ydiff > 0) {
		*ydiff = - comic->book->current_page->page_y;
	} else if  (*ydiff < 0 &&
	            (comic->book->current_page->page_y + *ydiff) < VHEIGHT() - comic->book->current_page->page_h ) {
		*ydiff = VHEIGHT() - comic->book->current_page->page_h - comic->book->current_page->y;
	}
}
static void _moving_with_mouse_temp(struct comic_reader_guis *comic, struct mouse_status *mouse) {
	int xdiff, ydiff;
	if (!comic) return;
	if (!comic->book) return;
	if (!mouse) return;

	_calculate_x_y_diff(comic, mouse, &xdiff, &ydiff);

	if (comic->book->last_page) {
		comic_page_turning_detail_temp (comic->book->last_page,
		                                comic->book->last_page->x + xdiff,
		                                comic->book->last_page->y + ydiff);
	}
	if (comic->book->current_page) {
		comic_page_turning_detail_temp (comic->book->current_page,
		                                comic->book->current_page->x + xdiff,
		                                comic->book->current_page->y + ydiff);
	}
	if (comic->book->next_page) {
		comic_page_turning_detail_temp (comic->book->next_page,
		                                comic->book->next_page->x + xdiff,
		                                comic->book->next_page->y + ydiff);
	}
}


static void _moving_with_mouse(struct comic_reader_guis *comic, struct mouse_status *mouse) {
	int xdiff, ydiff;
	if (!comic) return;
	if (!comic->book) return;
	if (!mouse) return;
	_moving_with_mouse_temp(comic, mouse);
	_calculate_x_y_diff(comic, mouse, &xdiff, &ydiff);
	if (comic->book->last_page) {
		comic->book->last_page->x += xdiff;
		comic->book->last_page->y += ydiff;
		comic->book->last_page->page_x += xdiff;
		comic->book->last_page->page_y += ydiff;
	}
	if (comic->book->current_page) {
		comic->book->current_page->x += xdiff;
		comic->book->current_page->y += ydiff;
		comic->book->current_page->page_x += xdiff;
		comic->book->current_page->page_y += ydiff;
	}
	if (comic->book->next_page) {
		comic->book->next_page->x += xdiff;
		comic->book->next_page->y += ydiff;
		comic->book->next_page->page_x += xdiff;
		comic->book->next_page->page_y += ydiff;
	}
}

void on_comic_mouse_cb_dummy(void *data, Evas *e, Evas_Object *obj, void *event_info) {
	debug("Event happened!!\n");
}

void on_comic_mouse_cb_down(void *data, Evas *e, Evas_Object *obj, void *event) {
	Evas_Event_Mouse_Down *ev = event;
	debug("Mouse down!!\n");
	if (!mouse) {
		mouse = (struct mouse_status *) malloc (sizeof(struct mouse_status));
		memset(mouse, 0, sizeof(struct mouse_status));
	}
	if (!mouse->pressed) {
		mouse->pressed = 1;
		mouse->x = mouse->s_x = ev->canvas.x;
		mouse->x = mouse->s_y = ev->canvas.y;
	}
	return;
}

void on_comic_mouse_cb_up(void *data, Evas *e, Evas_Object *obj, void *event) {
	Evas_Event_Mouse_Up *ev = event;
	if (!mouse) return;
	if (mouse->pressed) {
		debug("Mouse UP\n");
		mouse->pressed = 0;
		mouse->x = ev->canvas.x;
		mouse->y = ev->canvas.y;
		_moving_with_mouse(comic, mouse);
	}
}


void on_comic_mouse_cb_move(void *data, Evas *e, Evas_Object *obj, void *event) {
	Evas_Event_Mouse_Up *ev = event;
	int ret;
	if (!comic) return;
	if (!comic->book) return;
	if (!mouse) return;
	if (!mouse->pressed) {
		return;
	}
	mouse->x = ev->canvas.x;
	mouse->y = ev->canvas.y;
	ret = _check_if_change_page(comic, mouse);
	if (ret == 0) {
		_moving_with_mouse_temp(comic, mouse);
	} else {
		debug("Need to change to page %d\n", ret);
		mouse->pressed = 0;
		_moving_with_mouse(comic, mouse);
		// add animator here;
		if (ret == 1)
			comic_book_move_to_next(comic->book);
		else
			comic_book_move_to_last(comic->book);
	}
}

void on_comic_mouse_cb_out(void *data, Evas *e, Evas_Object *obj, void *event) {
	if (!mouse) return;
	if (mouse->pressed) {
		debug("Out of range!!\n");
		mouse->pressed = 0;
	}
}

void zoom_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event) {
	Evas_Event_Mouse_Down *ev = event;
	struct comic_book *book = (struct comic_book *) data;
	int x, y;
	if (!zoom_status) {
		zoom_status = (struct mouse_status *) malloc (sizeof(struct mouse_status));
		memset(zoom_status, 0, sizeof(struct mouse_status));
	}
	if (!zoom_status->pressed) {
		debug("Zoom pressed!\n");
		zoom_status->pressed = 1;
		evas_object_geometry_get(book->zoom, &x, &y, NULL, NULL);
		zoom_status->s_x = ev->canvas.x - x;
		zoom_status->s_y = ev->canvas.y - y;
		zoom_status->x = x;
		zoom_status->y = y;
	}
}

void zoom_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event) {
	Evas_Event_Mouse_Up *ev = event;
	struct comic_book *book = (struct comic_book *) data;
	if (!zoom_status) {
		zoom_status = (struct mouse_status *) malloc (sizeof(struct mouse_status));
		memset(zoom_status, 0, sizeof(struct mouse_status));
	}
	if (zoom_status->pressed) {
		zoom_status->pressed = 0;
		zoom_status->y =  ev->canvas.y - zoom_status->s_y >= 0 ? ev->canvas.y - zoom_status->s_y : 0;
		zoom_status->y = zoom_status->y <= VHEIGHT() - ZOOM_SIZE ? zoom_status->y : VHEIGHT() - ZOOM_SIZE;
		evas_object_move(book->zoom, 0, zoom_status->y);
	}
}

void zoom_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event) {
	Evas_Event_Mouse_Up *ev = event;
	struct comic_book *book = (struct comic_book *) data;
	int rate;
	if (!zoom_status) {
		zoom_status = (struct mouse_status *) malloc (sizeof(struct mouse_status));
		memset(zoom_status, 0, sizeof(struct mouse_status));
	}
	if (zoom_status->pressed) {
		zoom_status->y =  ev->canvas.y - zoom_status->s_y >= 0 ? ev->canvas.y - zoom_status->s_y : 0;
		zoom_status->y = zoom_status->y <= VHEIGHT() - ZOOM_SIZE ? zoom_status->y : VHEIGHT() - ZOOM_SIZE;
		evas_object_move(book->zoom, 0 , zoom_status->y);
		rate = 100 - 100 * zoom_status->y / (VHEIGHT() - ZOOM_SIZE);
		comic_book_scale_set(book, rate);
		debug("book->scale == %d\n", book->scale);
	}
}

